Stochastic Image Noising¶

  • In this notebook, I explored concept of Stochastic Image Noising using the Caltech 101 Dataset Faces. This technique involves adding random noise to images, which can be useful for various applications in image processing and data augmentation.

Dataset¶

  • I worked with the Caltech 101 Dataset Faces. This dataset contains a collection of face images, making it an excellent choice for our image noising experiment.

Stochastic Noise¶

  • Stochastic noise refers to random variations in pixel values that can be added to images. This noise can simulate real-world imperfections, sensor noise, or other environmental factors. By adding stochastic noise to images, we can achieve the following goals:
  • Data Augmentation: Noising images can increase the diversity of training data, potentially improving the performance of machine learning models.
  • Robustness Testing: Noised images can be used to test the robustness of computer vision algorithms and models to various forms of noise.
  • Privacy Protection: Noise can be added to images to protect sensitive information while retaining the overall structure.

Image Noise Types and Normalization¶

  • In this document, I explored different types of image noise and the concept of image normalization. These are fundamental topics in image processing and computer vision.

  • Normalization in image processing refers to the process of adjusting pixel values in an image to a standard range or distribution. Normalization techniques are used to enhance the quality and comparability of images. Common normalization methods include rescaling pixel values to a specific range (e.g., [0, 1] or [0, 255]), z-score normalization to have a mean of 0 and standard deviation of 1, and min-max scaling to map values to a desired range.

Each of these topics is important in image processing and computer vision and serves various purposes in image analysis and enhancement. Understanding these concepts can be invaluable in various applications, from denoising to feature extraction and machine learning.

  • Bernoulli Noise is a type of binary noise characterized by two possible values, typically 0 and 1, with predefined probabilities. It can be used to simulate events with a binary outcome, such as noisy pixel on/off states. Bernoulli noise is often used for simulating noisy sensors or for creating synthetic data for testing algorithms.

  • White Additive Noise is a common type of noise model that involves adding independent, identically distributed (i.i.d.) random values to each pixel in an image. It is called "white" because it exhibits a flat power spectral density, meaning it has a relatively equal distribution of noise energy across different frequencies. This type of noise is often used to simulate electronic or sensor noise.

  • Poisson Noise is a statistical noise model commonly associated with photon-counting processes. It manifests as random variations in pixel values and is often encountered in low-light imaging scenarios, such as astrophotography or medical imaging. Poisson noise can be characterized by its mean and variance, making it a useful model for certain imaging conditions.

Experiment¶

  • The experiment involves taking the Caltech 101 Dataset Faces and applying stochastic noise to the face images. The specific type and level of noise applied can vary based on the objectives of the experiment. There are various techniques to add noise, such as Gaussian noise, Poisson, Bernoulli

  • Feel free to explore different noise types and levels to see how it could impact the quality and robustness of the face recognition or image classification tasks.

In [ ]:
# Necessary Imports
import torch
import torch.nn as nn
import torch.optim as optim
import torchvision.datasets as datasets
import torchvision.transforms as transforms
from torch.utils.data import DataLoader
import torchvision
import matplotlib.pyplot as plt
import numpy as np
import torch.utils.data as data_utils
In [ ]:
# Load images and Preprocess 

transform = transforms.Compose([
    transforms.Resize((128, 128)),
    transforms.ToTensor(),
    
])

# Load the Caltech 101 dataset
caltech101 = datasets.Caltech101(root='data', transform=transform, download=True)

# Specify the subclass to load (for example, "Airplanes")

subclass_indices = [i for i in range(len(caltech101)) if caltech101[i][1] == 0] 
training_dataset = data_utils.Subset(caltech101, subclass_indices)

# Set train and test size
train_size = int(0.8 * len(training_dataset))
test_size = len(training_dataset) - train_size

# Train test split 80-20 %
train_dataset, test_dataset = torch.utils.data.random_split(training_dataset, [train_size, test_size])

# Load train and test dataset
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=32, shuffle=True, num_workers=4)
test_loader = torch.utils.data.DataLoader(test_dataset, batch_size=32, shuffle=False, num_workers=4)
Files already downloaded and verified
In [ ]:
# Visualize Images ne by one 
# Iterate over data loader

def imshow(ImageLoader):
    for batch in train_loader:
        # Get images and labels from the batch
        images, labels = batch
        
        # Visualize the images
        for i in range(images.size(0)):
            # Convert the image from tensor to numpy array
            image = images[i].numpy()
            
            # Undo the normalization transformation
            image = image * 0.5 + 0.5  # Assuming normalization mean=0.5 and std=0.5
            
            # Transpose image to (H, W, C) format
            image = np.transpose(image, (1, 2, 0))
            
            # Display image
            plt.imshow(image)
            plt.title(f'Label: {labels[i]}')
            plt.show()
            
            return images
        # Break after the first batch to visualize only a few images
        break

# Visualize images
images = imshow(train_loader)

Experimenting with noise¶

In [ ]:
# define function to view image each time
def imshow(image, ax=None, title=None, normalize=True):
    """Imshow for Tensor."""
    if ax is None:
        fig, ax = plt.subplots()
        image = image.numpy().transpose((1, 2, 0))

        if normalize:
          mean = np.array([0.485, 0.456, 0.406])
          std = np.array([0.229, 0.224, 0.225])
          image = std * image + mean
          image = np.clip(image, 0, 1)

    ax.imshow(image)
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)
    ax.spines['left'].set_visible(False)
    ax.spines['bottom'].set_visible(False)
    ax.tick_params(axis='both', length=0)
    ax.set_xticklabels('')
    ax.set_yticklabels('')

    return ax
In [ ]:
# Add Noise to entire dataset
# White Additive Noise
noisy_images = (images + torch.normal(0,0.2, images.shape)).clip(0,1)
In [ ]:
# View output noised images
for i in range(10):
  imshow(noisy_images[i], normalize=False)
In [ ]:
# Bernoulli Noise
a = 0.7*torch.ones(images.shape)
bernoulli_noisy_images = images*torch.bernoulli(a)
In [ ]:
# View output image
imshow(bernoulli_noisy_images[1], normalize=False)
Out[ ]:
<Axes: >
In [ ]:
# Poisson Noise 
a = 5*torch.ones(images.shape)
p = torch.poisson(a)
p_norm = p/p.max()
poisson_noisy_images = (images + p_norm).clip(0,1)

# View output Image
imshow(poisson_noisy_images[1], normalize=False)
Out[ ]:
<Axes: >